from calm.controller import Controller
from system.eventServer import eventServer
from ai.bin import decode

class LoopController(Controller):
    def __init__(self, parent, type = None, name = None):
        Controller.__init__(self,parent,type,name)
        
        self.defaultVar("numLoops",4)
        
        eventServer.register("initLoopController",self.initLoopController)
        
    def initLoopController(self, cmd, args):
        if args.has_key('path') and args['path'] != self.getVar("path"):
            return
        
        self.vars.update(args)
        
        self.calcNumBits()
        
        self.bits = args['ind']
        assert len(self.bits) == self.numBits, "genome size mismatch. wanted %d got %d" % (self.numBits,len(self.bits))
        
        self.loop = 0
        self.transition("active")
        
    def calcNumBits(self):
        numLoops = self.getVar("numLoops")
        self.numLoopIdBits = decode.minIntEncoding(numLoops)
        
        self.numSensorBits = sum([sensor.numBits for sensor in self.sensors.itervalues()])
        self.numActuatorBits = sum([actuator.numBits for actuator in self.actuators.itervalues()])
        
        self.numLoopBits = self.numActuatorBits + self.numSensorBits + self.numLoopIdBits
        self.numBits = self.numLoopBits * numLoops
        
        #print "sensor bits", self.numSensorBits
        #print "actuator bits", self.numActuatorBits
        #print "loopid bits", self.numLoopIdBits
        #print "loop bits", self.numLoopBits
        #print "loops", numLoops
        #print "bits", self.numBits
        
    def update_active(self, cmd, args):
        bitPos = self.numLoopBits * self.loop
        loopBits = self.bits[bitPos:bitPos+self.numLoopBits]
        
        actuatorBits = loopBits[:self.numActuatorBits]
        for actuator in self.actuators.itervalues():
            bits = actuatorBits[actuator.bitOffset:actuator.bitOffset+actuator.numBits]
            actuator.acceptBits(bits, args['dtime'])
        
        sensorBits = loopBits[self.numActuatorBits:self.numActuatorBits+self.numSensorBits]
        outBits = []
        for sensor in self.sensors.itervalues():
            bits = sensorBits[sensor.bitOffset:sensor.bitOffset+sensor.numBits]
            outBits.append(sensor.acceptBits(bits))
                
        if any(outBits):
            bitPos = self.numActuatorBits + self.numSensorBits
            numLoops = self.getVar("numLoops")
            self.loop = decode.decodeIntRange(loopBits,bitPos,self.numLoopIdBits,0,numLoops)
            #self.log("transition to loop %d" % self.loop)
